package cn.chiship.framework.business.core.aspect;

import cn.chiship.framework.common.annotation.SystemOptionAnnotation;
import cn.chiship.framework.common.pojo.dto.SystemOptionLogDto;
import cn.chiship.framework.common.util.FrameworkUtil2;
import cn.chiship.framework.upms.biz.system.entity.UpmsSystemOptionLog;
import cn.chiship.framework.upms.biz.system.service.UpmsSystemOptionLogService;
import cn.chiship.sdk.cache.service.UserCacheService;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.util.http.CustomRequestWrapper;
import cn.chiship.sdk.core.util.http.RequestUtil;
import cn.chiship.sdk.core.util.ip.IpUtils;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 * 日志记录AOP实现
 *
 * @author lijian
 */
@Aspect
@Component
public class LogAspect {

	private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);

	private static final String CONTENT_TYPE_APPLICATION_JSON = "application/json";

	private static final String STRING_METHOD_NAME = "methodName";

	@Resource
	private UpmsSystemOptionLogService upmsSystemOptionLogService;

	@Resource
	private UserCacheService userCacheService;

	/**
	 * 开始时间
	 */
	private long startTime = 0L;

	/**
	 * 结束时间
	 */
	private long endTime = 0L;

	@Before("execution(* *..controller..*.*(..))")
	public void doBeforeInServiceLayer(JoinPoint joinPoint) {
		LOGGER.debug("doBeforeInServiceLayer");
		startTime = System.currentTimeMillis();
	}

	@After("execution(* *..controller..*.*(..))")
	public void doAfterInServiceLayer(JoinPoint joinPoint) {
		LOGGER.debug("doAfterInServiceLayer");
	}

	@Around("execution(* *..controller..*.*(..))")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		/**
		 * 获取request
		 */
		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
		HttpServletRequest request = servletRequestAttributes.getRequest();
		/**
		 * 从注解中获取操作名称、获取响应结果
		 */
		Object result = pjp.proceed();
		Signature signature = pjp.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();

		SystemOptionAnnotation systemOption = method.getAnnotation(SystemOptionAnnotation.class);
		endTime = System.currentTimeMillis();
		LOGGER.debug("doAround>>>,耗时：{}", endTime - startTime);

		saveLog(request, result, systemOption);

		return result;
	}

	void saveLog(HttpServletRequest request, Object result, SystemOptionAnnotation systemOption) {
		UpmsSystemOptionLog upmsSystemOptionLog = new UpmsSystemOptionLog();
		upmsSystemOptionLog.setBasePath(RequestUtil.getBasePath(request));
		upmsSystemOptionLog.setIp(IpUtils.getIpAddr(request));
		upmsSystemOptionLog.setRequestType(request.getMethod());
		upmsSystemOptionLog.setResult(JSON.toJSONString(result));
		upmsSystemOptionLog.setSpendTime((int) (endTime - startTime));
		upmsSystemOptionLog.setStartTime(startTime);
		upmsSystemOptionLog.setUri(request.getRequestURI());
		upmsSystemOptionLog.setUserAgent(request.getHeader("User-Agent"));
		try {
			if (BaseConstants.HTTP_REQUEST_TYPE_GET.equalsIgnoreCase(request.getMethod())) {
				upmsSystemOptionLog.setParameter(request.getQueryString());
			}
			else {
				String contentType = request.getHeader("Content-Type");
				if (contentType.indexOf(CONTENT_TYPE_APPLICATION_JSON) >= 0) {
					CustomRequestWrapper requestWrapper = new CustomRequestWrapper(request);
					upmsSystemOptionLog.setParameter(requestWrapper.getBody());
				}
				else {
					upmsSystemOptionLog.setParameter(JSON.toJSONString(request.getParameterMap()));
				}

			}
			CacheUserVO userVO = userCacheService.getUser();
			if (userVO != null) {
				upmsSystemOptionLog.setUserId(userVO.getId());
				upmsSystemOptionLog.setUserName(userVO.getUsername());
				upmsSystemOptionLog.setRealName(userVO.getRealName());
			}
		}
		catch (Exception e) {
		}
		if (request.getAttribute(STRING_METHOD_NAME) != null) {
			upmsSystemOptionLog.setMethod(request.getAttribute(STRING_METHOD_NAME).toString());
		}
		if (null != systemOption) {
			upmsSystemOptionLog.setDescription(systemOption.describe());
			upmsSystemOptionLog.setOptionType(systemOption.option().getCode());
			upmsSystemOptionLog.setSystemName(systemOption.systemName());
			upmsSystemOptionLog.setOperatorType(systemOption.operatorType().toString());
			SystemOptionLogDto systemOptionLogDto = new SystemOptionLogDto();
			BeanUtils.copyProperties(upmsSystemOptionLog, systemOptionLogDto);
			FrameworkUtil2.formatInfoMessage(systemOptionLogDto);
			if (FrameworkUtil2.getChishipDefaultProperties().isEnableLogInterception()) {
				upmsSystemOptionLogService.insertSelective(upmsSystemOptionLog);
			}
		}

	}

}
